package com.m31skytech.ElasticTimer;

import com.m31skytech.ElasticTimer.service.ETRSSearchReq;
import com.m31skytech.ElasticTimer.service.ETRSSearchRes;
import com.m31skytech.ElasticTimer.service.IElasticTimerRemoteService;
import com.m31skytech.ElasticTimer.timer.ElasticTimerConfig;
import com.alibaba.dubbo.common.URL;

import com.alibaba.dubbo.common.utils.UrlUtils;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.fastjson.JSON;
import com.m31skytech.ElasticTimer.utils.ZookeeperHelper;
import com.netflix.curator.RetryPolicy;
import com.netflix.curator.framework.CuratorFramework;
import com.netflix.curator.framework.CuratorFrameworkFactory;
import com.netflix.curator.framework.recipes.cache.PathChildrenCache;
import com.netflix.curator.framework.state.ConnectionState;
import com.netflix.curator.framework.state.ConnectionStateListener;
import com.netflix.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@Component
public class ElasticTimerCuratorHandleService {
    static final String NAME_SPACES="com.m31skytech.elastictimer";
    static final String CONFIG_CHECK_PATH="/config/time_tag";   //use to check
    static final String CONFIG_CHECK_PATH_PERSISTENT="/config/time_tag/persistent"; //use to modify
    static final String CONFIG_PROPERTIES_PATH="/config/properties";    //use to check
    static final String CONFIG_PROPERTIES_PATH_PERSISTENT="/config/properties/persistent";  //use to modify

    static final String CONFIG_PLACE="elastictimer";

    static final String CONFIG_TYPE="elastictimer.config.type";
    static final String CONFIG_TYPE_VALUE_PROXY="proxy";
    static final String CONFIG_TYPE_VALUE_DIRECT ="direct";
    static final String CONFIG_TYPE_DEFAULTVALUE="direct";


    static final String CONFIG_PROXY_FILENAME="elastictimer.config.proxy.filename";
    static final String CONFIG_PROXY_FILENAME_DEFAULTVALUE="dubbo.properties";

    static final String CONFIG_ZOOKEEPER_PATH="elastictimer.zookeeper.path";    //ZKPATH
    static final String CONFIG_ZOOKEEPER_ORIPATH="elastictimer.zookeeper.ori_path";    //ZKPATH

    static final String CONFIG_ZOOKEEPER_PATH_DEFAULTVALUE="zookeeper://127.0.0.1:2181";    //ZKPATH
    static final String CONFIG_PROXY_ZOOKEEPER_PATH="elastictimer.config.proxy.zookeeper.path";
    static final String CONFIG_PROXY_ZOOKEEPER_PATH_DEFAULTVALUE="dubbo.registry.address";

    static final String CONFIG_APP_CODE="elastictimer.application.code";    //APPNAME
    static final String CONFIG_APP_CODE_DEFAULTVALUE="ElasticTimerApp";    //APPNAME
    static final String CONFIG_PROXY_APP_CODE="elastictimer.config.proxy.application.code";
    static final String CONFIG_PROXY_APP_CODE_DEFAULTVALUE="dubbo.application.name";

    static final String CONFIG_OWNER_CODE="elastictimer.owner.code";    //OWNERNAME
    static final String CONFIG_OWNER_CODE_DEFAULTVALUE="M31";    //OWNERNAME
    static final String CONFIG_PROXY_OWNER_CODE="elastictimer.config.proxy.owner.code";
    static final String CONFIG_PROXY_OWNER_CODE_DEFAULTVALUE="dubbo.application.owner";

    static final String CONFIG_DUBBOPORT="elastictimer.dubbo.port"; //USEDUBBOPORT
    static final String CONFIG_DUBBOPORT_DEFAULTVALUE="20880"; //USEDUBBOPORT
    static final String CONFIG_PROXY_DUBBOPORT="elastictimer.config.proxy.dubbo.port";
    static final String CONFIG_PROXY_DUBBOPORT_DEFAULTVALUE="dubboPort";


    private Map<String,Object> configPropertiesMapping=new HashMap<>();
    private ExecutorService executorService= Executors.newFixedThreadPool(10);
    private CuratorFramework curatorFrameworkClient;
    private boolean prerared=false;

    static Logger logger= LoggerFactory.getLogger(ElasticTimerCuratorHandleService.class);
    public ElasticTimerCuratorHandleService() {
        try{
            //find properties
            findConfigElasticTimerProperties();logger.info("findConfigElasticTimerProperties done.");prerared=true;
            //init curatorClient
            initCuratorClient();
            //register nodes
            registerElasticTimerServiceNode();
        }catch (Exception e){
            logger.error("something wrong when init .",e);
            if(null!=curatorFrameworkClient){
                curatorFrameworkClient.close();
                curatorFrameworkClient.delete();
                curatorFrameworkClient=null;logger.info("curator client cached clear.");
            }
            prerared=false;
        }
    }


    /**
     *
     * @param resourceBundle
     */
    private void proxyConfigPropertiesSetting(ResourceBundle resourceBundle){
        String fileNameProxy=null;
        if(null!=resourceBundle.getString(CONFIG_PROXY_FILENAME)){
            fileNameProxy=resourceBundle.getString(CONFIG_PROXY_FILENAME);
        }else{
            fileNameProxy=CONFIG_PROXY_FILENAME_DEFAULTVALUE;
        }
        ResourceBundle resourceBundlepProxy=ResourceBundle.getBundle(fileNameProxy.split("\\.")[0]);

        //zkaddress
        String zkaddress=null;
        String originZkaddress=null;
        if(null!=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_ZOOKEEPER_PATH))){
            originZkaddress=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_ZOOKEEPER_PATH));
            zkaddress=ZookeeperHelper.convertToZookeeperString(originZkaddress);
        }else{
            originZkaddress=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_ZOOKEEPER_PATH_DEFAULTVALUE));
            zkaddress=ZookeeperHelper.convertToZookeeperString(originZkaddress);
            logger.warn("config not find, use default zkaddress >> "+zkaddress);
        }
        configPropertiesMapping.put(CONFIG_ZOOKEEPER_PATH,zkaddress);
        configPropertiesMapping.put(CONFIG_ZOOKEEPER_ORIPATH,originZkaddress);

        //appname
        String appname=null;
        if(null!=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_APP_CODE))){
            appname=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_APP_CODE));
        }else{
            appname=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_APP_CODE_DEFAULTVALUE));
            logger.warn("config not find, use default appname >> "+appname);
        }
        configPropertiesMapping.put(CONFIG_APP_CODE,appname);

        //ownercode
        String ownercode=null;
        if(null!=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_OWNER_CODE))){
            ownercode=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_OWNER_CODE));
        }else{
            ownercode=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_OWNER_CODE_DEFAULTVALUE));
            logger.warn("config not find, use default ownercode >> "+ownercode);
        }
        configPropertiesMapping.put(CONFIG_OWNER_CODE,ownercode);

        //dubboport
        String dubboPort=null;
        if(null!=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_DUBBOPORT))){
            dubboPort=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_DUBBOPORT));
        }else{
            dubboPort=resourceBundlepProxy.getString(resourceBundle.getString(CONFIG_PROXY_DUBBOPORT_DEFAULTVALUE));
            logger.warn("config not find, use default dubboport >> "+dubboPort);
        }
        configPropertiesMapping.put(CONFIG_DUBBOPORT,dubboPort);
    }

    /**
     *
     * @param resourceBundle
     */
    private void directConfigPropertiesSetting(ResourceBundle resourceBundle){
        //zkaddress
        String zkaddress=null;
        String originZkaddress=null;
        if(null!=resourceBundle.getString(CONFIG_ZOOKEEPER_PATH)){
            originZkaddress=resourceBundle.getString(CONFIG_ZOOKEEPER_PATH);
            zkaddress=ZookeeperHelper.convertToZookeeperString(originZkaddress);
        }else{
            originZkaddress=resourceBundle.getString(CONFIG_ZOOKEEPER_PATH_DEFAULTVALUE);
            zkaddress=ZookeeperHelper.convertToZookeeperString(originZkaddress);
            logger.warn("config not find, use default zkaddress >> "+zkaddress);
        }
        configPropertiesMapping.put(CONFIG_ZOOKEEPER_ORIPATH,originZkaddress);
        configPropertiesMapping.put(CONFIG_ZOOKEEPER_PATH,zkaddress);

        //appname
        String appname=null;
        if(null!=resourceBundle.getString(CONFIG_APP_CODE)){
            appname=resourceBundle.getString(CONFIG_APP_CODE);
        }else{
            appname=resourceBundle.getString(CONFIG_APP_CODE_DEFAULTVALUE);
            logger.warn("config not find, use default appname >> "+appname);
        }
        configPropertiesMapping.put(CONFIG_APP_CODE,appname);

        //ownercode
        String ownercode=null;
        if(null!=resourceBundle.getString(CONFIG_OWNER_CODE)){
            ownercode=resourceBundle.getString(CONFIG_OWNER_CODE);
        }else{
            ownercode=resourceBundle.getString(CONFIG_OWNER_CODE_DEFAULTVALUE);
            logger.warn("config not find, use default ownercode >> "+ownercode);
        }
        configPropertiesMapping.put(CONFIG_OWNER_CODE,ownercode);

        //dubboport
        String dubboPort=null;
        if(null!=resourceBundle.getString(CONFIG_DUBBOPORT)){
            dubboPort=resourceBundle.getString(CONFIG_DUBBOPORT);
        }else{
            dubboPort=resourceBundle.getString(CONFIG_DUBBOPORT_DEFAULTVALUE);
            logger.warn("config not find, use default dubboport >> "+dubboPort);
        }
        configPropertiesMapping.put(CONFIG_DUBBOPORT,dubboPort);
    }


    private void findConfigElasticTimerProperties() throws Exception {
        ResourceBundle resourceBundle=ResourceBundle.getBundle(CONFIG_PLACE);
        if(resourceBundle.containsKey(CONFIG_TYPE) &&CONFIG_TYPE_VALUE_PROXY.equals(resourceBundle.getString(CONFIG_TYPE))){
            proxyConfigPropertiesSetting(resourceBundle);
        }else if(resourceBundle.containsKey(CONFIG_TYPE) && CONFIG_TYPE_VALUE_DIRECT.equals(resourceBundle.getString(CONFIG_TYPE))){
            directConfigPropertiesSetting(resourceBundle);
        }else {
            throw new Exception("must setting "+CONFIG_TYPE+" value in "+CONFIG_PLACE+".properties");
        }
        ResourceBundle.clearCache();
    }

    private void initCuratorClient() throws  Exception{
        if(configPropertiesMapping.isEmpty())throw new Exception("undefine config ,cancel to init curator client");
        if(!configPropertiesMapping.containsKey(CONFIG_ZOOKEEPER_PATH))throw new Exception(CONFIG_ZOOKEEPER_PATH+" unknow ,cancel to init curator client");
        if(!configPropertiesMapping.containsKey(CONFIG_APP_CODE))throw new Exception(CONFIG_APP_CODE+" unknow ,cancel to init curator client");
        if(!configPropertiesMapping.containsKey(CONFIG_OWNER_CODE))throw new Exception(CONFIG_OWNER_CODE+" unknow ,cancel to init curator client");
        if(!configPropertiesMapping.containsKey(CONFIG_DUBBOPORT))throw new Exception(CONFIG_DUBBOPORT+" unknow ,cancel to init curator client");
        //do init curator client
        //1     define retryPolicy
        getCuratorFrameworkClient();
        logger.info("curator client init done.");
    }

    private void registerElasticTimerServiceNode() throws Exception {
//        curatorFrameworkClient .create().creatingParentsIfNeeded()
//                .withMode(CreateMode.PERSISTENT)
//                .forPath("/config","init".getBytes());
//        if(curatorFrameworkClient.checkExists().)
        //TODO 如何保障必有一节点成功?
        String timetag_node="/config/time_tag";
        String timetag_node_p="/config/time_tag/persistent";

        try{
            if(null==curatorFrameworkClient.checkExists().forPath(timetag_node_p)){
                curatorFrameworkClient.create().creatingParentsIfNeeded()
                        .forPath(timetag_node_p,String.valueOf(System.currentTimeMillis()).getBytes());
            }
        }catch (Exception e){
            logger.error("node may not be make sure.\n"+e.getLocalizedMessage());
        }
        //check again
        //try to watch node
        if(null!=curatorFrameworkClient.checkExists().forPath(timetag_node_p)){
//            curatorFrameworkClient.getData().usingWatcher(new ElasticTimeTagWatcher()).forPath(timetag_node);
            //为子节点添加watcher
            PathChildrenCache childrenCache = new PathChildrenCache(curatorFrameworkClient,timetag_node,true);
            /**
             * StartMode：初始化方式
             *  NORMAL：普通异步初始化
             BUILD_INITIAL_CACHE:同步初始化
             POST_INITIALIZED_EVENT：异步初始化，初始化之后会触发事件
             */
            childrenCache.start(true);
            childrenCache.getListenable().addListener(new ElasticTimeTagListener(),executorService);



            logger.info("ElasticTimeTagWatcher register success.");
        }else{
            logger.error("cant't make sure node exist, check after for Retry.\n this is a fatal issue must be check out!!.");
        }

//
//        Collection<CuratorTransactionResult> results= getCuratorFrameworkClient().inTransaction().check().forPath("/config/time_tag")
//                .and().create().withMode(CreateMode.PERSISTENT).forPath("/config/time_tag",String.valueOf(System.currentTimeMillis()).getBytes())
//                .and().commit();
//        System.out.println(results);



        logger.info("elastictimer config node init done.");

    }

    public String notifyElasticTimerServiceNodeUpdate() throws Exception {
        this.getCuratorFrameworkClient().setData().forPath("/config/time_tag/persistent",String.valueOf(System.currentTimeMillis()).getBytes());
        logger.info("notifyElasticTimerServiceNodeUpdate success .");
        Stat stattemp=new Stat();
        return new String(this.getCuratorFrameworkClient().getData().storingStatIn(stattemp).forPath("/config/time_tag/persistent"));
    }








    public CuratorFramework getCuratorFrameworkClient() throws Exception {
        if(!prerared){
            throw new Exception("env not prepared. please check ur config");
        }
        if (null == curatorFrameworkClient) {
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            curatorFrameworkClient =
                    CuratorFrameworkFactory.builder()
                            .connectString((String) configPropertiesMapping.get(CONFIG_ZOOKEEPER_PATH))
                            .sessionTimeoutMs(5000)
                            .connectionTimeoutMs(20000)
                            .retryPolicy(retryPolicy)
                            .namespace(NAME_SPACES+"."+configPropertiesMapping.get(CONFIG_OWNER_CODE)+"."+configPropertiesMapping.get(CONFIG_APP_CODE))
                            .build();
            curatorFrameworkClient.getConnectionStateListenable().addListener(new ElasticTimerConnectionListener());
            curatorFrameworkClient.start();
        }
            return curatorFrameworkClient;
    }


    /**判断持久化配置节点是否存在
     *
     * @return
     * @throws Exception
     */
    public boolean ifConfigPropertiesPersistentExits() throws Exception {
        return null!=getCuratorFrameworkClient().checkExists().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT);
    }



    public boolean syncTimerConfig(ElasticTimerConfig elasticTimerConfig) throws Exception{
        if(null!=getCuratorFrameworkClient().checkExists().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT)){
            //check same
            Stat stattemp=new Stat();
            String dataRemote= new String(this.getCuratorFrameworkClient().getData().storingStatIn(stattemp).forPath(CONFIG_PROPERTIES_PATH_PERSISTENT));
            try{
                ElasticTimerConfig remoteConfig=JSON.parseObject(dataRemote,ElasticTimerConfig.class);
                if(null==remoteConfig){
                    this.getCuratorFrameworkClient().setData().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT, JSON.toJSONString(elasticTimerConfig).getBytes());
                    logger.info("remote none, update remote.");
                }else{
                    if(remoteConfig.equals(elasticTimerConfig)){
                        logger.info("is same no need update remote.");
                    }else{
                        this.getCuratorFrameworkClient().setData().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT, JSON.toJSONString(elasticTimerConfig).getBytes());
                        logger.info("remote different, update remote.");
                    }
                }
            }catch (Exception e){
                this.getCuratorFrameworkClient().setData().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT, JSON.toJSONString(elasticTimerConfig).getBytes());
                logger.warn("parse error ,update remote.");
            }
        }else{
            this.getCuratorFrameworkClient().create().creatingParentsIfNeeded().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT, JSON.toJSONString(elasticTimerConfig).getBytes());
            logger.info("remote no exist, update remote.");
        }
        return true;
    }

    public boolean dropRemoteConfig() throws Exception {
        if(null!=getCuratorFrameworkClient().checkExists().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT)){
            getCuratorFrameworkClient().delete().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT);
            return true;
        }
        return false;
    }


    /**
     *
     * @return
     * @throws Exception
     */
    public ElasticTimerConfig getRemoteConfig() throws Exception {
        if(null==getCuratorFrameworkClient().checkExists().forPath(CONFIG_PROPERTIES_PATH_PERSISTENT))return null;
        try{
            Stat stattemp=new Stat();
            String dataRemote= new String(this.getCuratorFrameworkClient().getData().storingStatIn(stattemp).forPath(CONFIG_PROPERTIES_PATH_PERSISTENT));
            ElasticTimerConfig remoteConfig=JSON.parseObject(dataRemote,ElasticTimerConfig.class);
            return remoteConfig;
        }catch (Exception e){
            return null;
        }
    }

    public List<Service> getAllDubboCurrentAliveProviderNodes(String serviceUrl,String owner,String appname){
        //TODO USE DEFAULT SAME ZKURL
//        CuratorFramework curatorFrameworkTemp=null;
        List<Service> services=new ArrayList<>();
        try{
//            curatorFrameworkTemp=getTempCuratorClient();
//            curatorFrameworkTemp.start();
            List<String> stringList=
//                    curatorFrameworkTemp.getChildren().forPath("/dubbo/"+serviceUrl+"/providers");
            curatorFrameworkClient.getZookeeperClient().getZooKeeper().getChildren("/dubbo/"+serviceUrl+"/providers",false);
                    URL _url=null;
            for(String str:stringList){
                _url= UrlUtils.parseURL(URL.decode(str),null);
                if( null!=owner &&!((String)_url.getParameter("owner")).equals(owner))continue;
                if( null!=appname &&!((String)_url.getParameter("application")).equals(appname))continue;
                if(!_url.getProtocol().equals("dubbo"))continue;
                Service service=new Service();
                service.setApplicationCode(_url.getParameter("application"));
                service.setHost(_url.getHost());
                service.setMethods(_url.getParameter("methods"));
                service.setPort(_url.getPort());
                service.setProtocol(_url.getProtocol());
                service.setOwner(_url.getParameter("owner"));
                service.setRevision(_url.getParameter("revision"));
                service.setVersion(_url.getParameter("version"));
                services.add(service);
            }
            return services;
        }catch (Exception e){
            logger.error("can not get Service Data.>>",e);
            return new ArrayList<>();
        }finally {
//            if(null!=curatorFrameworkTemp){
//                curatorFrameworkTemp.close();
//            }
        }
    }


    public CuratorFramework getTempCuratorClient() throws IOException {
            CuratorFramework curatorFrameworkTemp=null;
            RetryPolicy retryPolicy = new ExponentialBackoffRetry(1000, 3);
            curatorFrameworkTemp =
                    CuratorFrameworkFactory.builder()
                            .connectString((String) configPropertiesMapping.get(CONFIG_ZOOKEEPER_PATH))
                            .sessionTimeoutMs(5000)
                            .connectionTimeoutMs(20000)
                            .retryPolicy(retryPolicy)
                            .namespace("/")
                            .build();
            curatorFrameworkTemp.getConnectionStateListenable().addListener(new ConnectionStateListener() {
                @Override
                public void stateChanged(CuratorFramework curatorFramework, ConnectionState state) {
                    if (state == ConnectionState.LOST) {
                        //连接丢失
                        logger.info("lost session with zookeeper");
                    } else if (state == ConnectionState.CONNECTED) {
                        //连接新建
                        logger.info("connected with zookeeper");
                    } else if (state == ConnectionState.RECONNECTED) {
                        logger.info("reconnected with zookeeper");
                        //连接重连
//                        for(IZkStateListener s:st){
//                            s.reconnected();
//                        }
                    }

                }
            });
            return curatorFrameworkTemp;
        }

        public IElasticTimerRemoteService getTargetIpElasticRemoteService(Service service){
            ReferenceConfig<IElasticTimerRemoteService> reference=new ReferenceConfig<>();
            ApplicationConfig config=new ApplicationConfig();
            config.setName(getCurrentAppname()+"_master");
            config.setOwner(getCurrentOwner()+"_master");
            RegistryConfig registryConfig=new RegistryConfig();
            registryConfig.setAddress("zookeeper://"+getCurentZookeeper());
            reference.setApplication(config);
            //
            reference.setUrl(service.getHost()+":"+service.getPort());
            reference.setInterface(IElasticTimerRemoteService.class);
            reference.setVersion(service.getVersion());
            reference.setTimeout(50000);
            reference.setProtocol(service.getProtocol());
            IElasticTimerRemoteService serviceTarget=reference.get();
            return serviceTarget;
        }
        public ElasticTimerConfig getTargetIpLocalElasticTimerConfig(Service service){
            ReferenceConfig<IElasticTimerRemoteService> reference=new ReferenceConfig<>();
            try{
            ApplicationConfig config=new ApplicationConfig();
            config.setName(getCurrentAppname());
            config.setOwner(getCurrentOwner());
            RegistryConfig registryConfig=new RegistryConfig();
            registryConfig.setAddress("zookeeper://"+getCurentZookeeper());
            reference.setApplication(config);
            //
            reference.setUrl(service.getHost()+":"+service.getPort());
            reference.setInterface(IElasticTimerRemoteService.class);
            reference.setVersion(service.getVersion());
            reference.setTimeout(50000);
            reference.setProtocol(service.getProtocol());
            IElasticTimerRemoteService serviceTarget=reference.get();
               ETRSSearchRes res=serviceTarget.search(new ETRSSearchReq());
               return res.getElasticTimerConfig();
           }catch (Exception e){
                logger.error("get Remote Service Config err >> "+e.getLocalizedMessage());
                return null;
            }finally {
               reference.destroy();
           }
        }







        public String getCurrentAppname(){
            return (String) configPropertiesMapping.get(CONFIG_APP_CODE);
        }

        public String getCurrentOwner(){
            return (String) configPropertiesMapping.get(CONFIG_OWNER_CODE);
        }
        public String getCurentZookeeper(){
            return (String) configPropertiesMapping.get(CONFIG_ZOOKEEPER_PATH);
        }
        public String getCurrentOriginZookeeper(){
            return (String) configPropertiesMapping.get(CONFIG_ZOOKEEPER_ORIPATH);
        }
        public String getCurrentDubboPort(){
        return (String) configPropertiesMapping.get(CONFIG_DUBBOPORT);
        }



    public static class Service{
        private String protocol;
        private String owner;
        private String applicationCode;
        private String host;
        private int port;
        private String revision;
        private String version;
        private String methods;

        public String getProtocol() {
            return protocol;
        }

        public void setProtocol(String protocol) {
            this.protocol = protocol;
        }

        public String getOwner() {
            return owner;
        }

        public void setOwner(String owner) {
            this.owner = owner;
        }

        public String getApplicationCode() {
            return applicationCode;
        }

        public void setApplicationCode(String applicationCode) {
            this.applicationCode = applicationCode;
        }

        public String getHost() {
            return host;
        }

        public void setHost(String host) {
            this.host = host;
        }

        public int getPort() {
            return port;
        }

        public void setPort(int port) {
            this.port = port;
        }

        public String getRevision() {
            return revision;
        }

        public void setRevision(String revision) {
            this.revision = revision;
        }

        public String getVersion() {
            return version;
        }

        public void setVersion(String version) {
            this.version = version;
        }

        public String getMethods() {
            return methods;
        }

        public void setMethods(String methods) {
            this.methods = methods;
        }
    }
}

